package com.imm.net.http.base

import android.util.Log
import androidx.lifecycle.MutableLiveData
import com.imm.net.http.TAG
import com.imm.net.http.base.interceptor.HeadInterceptor
import com.imm.net.http.base.interceptor.HttpInterceptor
import com.imm.net.http.base.interceptor.LogInterceptor
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.security.cert.X509Certificate
import java.util.concurrent.TimeUnit
import javax.net.ssl.X509TrustManager

/**
 * <p>------------------------------------------------------
 * <p> Copyright (C) 2021 zhangmz, All rights reserved.
 * <p> If there is technical discussion, you can contact zhangmz90@foxmail.com
 * <p>------------------------------------------------------
 * <p> des
 * <p>
 *
 * @author Created by zhangmz90
 * @date on 2021 2021/11/14 13:39
 */
open class BaseHttpFactory constructor(baseUrl : String) {

    companion object{
        /**
         * 链接超时时间
         */
        private const val CONNECT_TIME_OUT = 10L

        /**
         * 内存读写时间
         */
        private const val READ_TIME_OUT = 8L
    }

    private var mRetrofit : Retrofit

    init {
        val trustAllCert: X509TrustManager = object : X509TrustManager {
            override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) {
            }
            override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) {
            }
            override fun getAcceptedIssuers(): Array<X509Certificate> {
                return arrayOf()
            }
        }

        val loggingInterceptor = HttpLoggingInterceptor(LogInterceptor())
        loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY

        val builder = OkHttpClient.Builder()
        builder
            .sslSocketFactory(SSLSocketFactoryCompat(trustAllCert), trustAllCert)
            .connectTimeout(CONNECT_TIME_OUT, TimeUnit.SECONDS)
            .readTimeout(READ_TIME_OUT, TimeUnit.SECONDS)
            .writeTimeout(READ_TIME_OUT, TimeUnit.SECONDS)
            // 超时重连
            .retryOnConnectionFailure(true)
            .addInterceptor(loggingInterceptor)
            .addInterceptor(HeadInterceptor())
            .addInterceptor(HttpInterceptor())

        mRetrofit = Retrofit.Builder()
            .client(builder.build())
            .addConverterFactory(GsonConverterFactory.create())
            .baseUrl(baseUrl)
            .build()
    }

    fun <T> create(service : Class<T>) : T = mRetrofit.create(service)

    fun <T> enqueue(
        call: Call<T>,
        data : MutableLiveData<T>,
        error : () -> Unit = {},
        complete : () -> Unit = {}
    ) {
        call.enqueue(object : Callback<T> {
            override fun onResponse(call: Call<T>, response: Response<T>) {
                data.value = response.body()
                complete()
            }
            override fun onFailure(call: Call<T>, t: Throwable) {
                t.printStackTrace()
                error()
                complete()
            }
        })
    }

    fun <T> enqueue(
        call: Call<T>,
        success : (result: T) -> Unit,
        failure : (e: Throwable) -> Unit = {  },
        complete : () -> Unit = {  }
    ) {
        call.enqueue(object : Callback<T> {
            override fun onResponse(call: Call<T>, response: Response<T>) {
                response.body()?.let(success)?: Log.e(TAG, "response response is null")
                complete()
            }
            override fun onFailure(call: Call<T>, t: Throwable) {
                t.printStackTrace()
                failure(t)
                complete()
            }
        })
    }

}